package com.cn.demo.springboot.globalexception.service;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cn.demo.springboot.vo.ResponseMsg;


public class HandlerExceptionResolverImpl implements HandlerExceptionResolver {
	private final static Logger log = LoggerFactory.getLogger(HandlerExceptionResolverImpl.class);
	
	@Autowired(required = false)
	private  ViewNameInterfaces viewNameInterfaces;

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {

		log.error("全局异常处理开始");
		HttpStatus status = getStatus(request);
		int code = getCode(ex, status);
		String message = getMessage(ex, code);
		if (handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			if (handlerMethod.getMethodAnnotation(ResponseBody.class) != null) {
				ResponseMsg<Object> responseMsg = new ResponseMsg<Object>();
				responseMsg.setMsg(message);
				responseMsg.setStatus(code);
				responseOutWithJson(response, responseMsg);
				log.error("全局异常处理信息 ---> {}", message);
				log.error("全局异常处理结束");
				return null;
			}
		}

		String viewName = null;

		viewName = getViewName(ex, status, handler);

		viewName = viewName == null ? "error500" : viewName;
		log.error("全局异常处理信息 ---> {}", message);
		log.error("全局异常处理结束");
		return new ModelAndView(viewName).addObject("timestamp", System.currentTimeMillis()).addObject("error", "error")
				.addObject("status", status).addObject("message", message).addObject("code", code);
	}

	
	protected String getMessage(Exception ex,int code) {
		if(403 == code) {
			return " 403 啊 403 ";
		}else {
			return ex.getMessage();
		}
	}
	
	/**
	 * 获取错误视图名称
	 * 
	 * @param ex
	 * @param status
	 * @param handler
	 * @return
	 */
	protected String getViewName(Exception ex, HttpStatus status, Object handler) {
		if (viewNameInterfaces != null) {
			return viewNameInterfaces.getViewName(ex, status, handler);
		}
		return null;
	}

	/**
	 * 自定义异常code
	 * 
	 * @param ex
	 * @return
	 */
	protected int getCode(Exception ex, HttpStatus status) {

		if (ex instanceof AuthorizationException) {
			
			return ResponseMsg.AUTHORIZATION_DENIED;
		}
		// TODO: 自定义异常code

		return ResponseMsg.STATUS_FAILED;
	}

	protected void responseOutWithJson(HttpServletResponse response, Object responseObject) {
		// 将实体对象转换为JSON Object转换
		JSONObject responseJSONObject = (JSONObject) JSON.toJSON(responseObject);
		// JSONObject responseJSONObject =
		// JSONObject.fromObject(responseObject);
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			out.append(responseJSONObject.toString());
			log.error("异常返回值，{}", responseJSONObject.toString());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}

	protected HttpStatus getStatus(HttpServletRequest request) {
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		if (statusCode == null) {
			return HttpStatus.INTERNAL_SERVER_ERROR;
		}
		try {
			return HttpStatus.valueOf(statusCode);
		} catch (Exception ex) {
			return HttpStatus.INTERNAL_SERVER_ERROR;
		}
	}
}
